package com.acando.feide.utils;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.codec.binary.Base64;

public class LDIFUtil {

    /**
     * This is used to write a value that is *probably* normal string encoded, but *may* need to be base64 encoded. It
     * checks the string against the requirements of draft-good-ldap-ldif-04 (initial character sane, subsequent
     * characters not null, CR or LF), and returns the appropriate string, with appropriate ': ' or ':: ' prefix.
     * 
     * @param s
     *            the string to be ldif encoded
     * @return the ldif encoding (possibly base64) with appropriate colons.
     */

    public static String ldifEncode(String s) {
        boolean base64Encode = false;

        int len = s.length();

        if (len == 0)
            return ": "; // this shouldn't really happen;

        // run the rfc tests to see if this is a good and virtuous string
        char startChar = s.charAt(0);
        if ("\n\r :".indexOf(startChar) != -1) // check for safe start char
            base64Encode = true;
        char test[] = new char[len];
        s.getChars(0, len, test, 0);
        for (int i = 0; i < len; i++) {
            if (test[i] > 126 || test[i] < 32) // check for sane intermediate chars
            {
                base64Encode = true; // (may be unicode international string)
                break;
            }
        }

        if (s.charAt(s.length() - 1) == ' ') // end space considered harmful
            base64Encode = true;

        if (base64Encode) {
            try {
                byte[] bytes = Base64.encodeBase64(s.getBytes("UTF8"));
                s = new String(bytes);
            } catch (UnsupportedEncodingException e) {
                // Cannot happen....
            }

            return ":: " + s;
        } else
            return ": " + s; // return unmodified string.
    }

    /**
     * MD5 encrypt the given password
     * 
     * @param password
     * @return Encrypted password as a String of hex values.
     */
    public static String encryptToMD5(String password) {
        try {
            MessageDigest md = MessageDigest.getInstance("md5");
            byte[] p = md.digest(password.getBytes());
            StringBuffer hexString = new StringBuffer();
            for (int i = 0; i < p.length; i++) {
                hexString.append(Integer.toHexString(0xFF & p[i]));
            }
            password = hexString.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return password;
    }
    
    /**
     * Format norwegian telephone numbers. 
     * 
     * First an eventual "+47" part is removed.
     * 
     * All characters not digits (0-9) is removed
     * 
     * Check that exactly 8 digits is left
     * 
     * Format a number like +47 12 34 56 78
     * 
     * @param nbr   input string of nbr to format
     * @return      the formatted string
     * @throws AppException
     */
    public static String formatPhoneNbr(String nbr) throws AppException {
        Pattern p = Pattern.compile("\\+47|\\D"); 
        Matcher matcher = p.matcher(nbr);
        String nbr2 = matcher.replaceAll("");
        if (nbr2.length() != 8) {
            // If we didn't find a 8 digit number we use the original string as it is
            return nbr;
        }
        StringBuffer sb = new StringBuffer();
        sb.append("+47 ");
        sb.append(nbr2.substring(0, 2));
        sb.append(" ");
        sb.append(nbr2.substring(2, 4));
        sb.append(" ");
        sb.append(nbr2.substring(4, 6));
        sb.append(" ");
        sb.append(nbr2.substring(6, 8));
        return sb.toString();
    }

}
